package tp.model;

import java.awt.Component;
import java.util.*;

import tp.controller.Controlador;
import tp.view.*;

/**
 * @author Dr Von Nostrum misil, clase
 */
public class Misil extends Observable implements Chocable {

	/**
	 * tiene posicion del tipo posicion
	 */
	public Posicion MiPosicion;

	public MisilView miVista;

	String Clase = "Misil";

	/**
	 * tiene posicionvieja del tipo posicion, que sirve para saber donde estaba
	 * antes de moverse
	 */
	public Posicion MiPosicionVieja = new Posicion(0, 0);

	/**
	 * la direccion esta dada por el vector (0.0;0.0) y miDireccion
	 */
	public Posicion MiDireccion;

	/**
	 * la cantidad de posiciones que se mueve sobre la traza del vector
	 * direccion y su posicion
	 */
	public int MiVelocidad = 1;

	/**
	 * es una referencia a la lista de chocables
	 */
	private ColChocables ListaChocables;

	/**
	 * este es el radio de accion del misil para que detone
	 */
	private double MiRadio = 10;

	private boolean vivo = true;

	public Misil(Posicion pos) {
		this.setMiPosicion(pos);
		this.setVelocidad(3);
		this.setMiDireccion(0, 1);
		// CopyOfBoardView1.addVisible(new MisilView(this));
		miVista = new MisilView(this);
		Controlador.controlador.addChocable(this);
	}

	/**
	 * para calcular la direccion en la cual este esta yendo
	 * 
	 * @param X
	 * @param Y
	 */
	public void setMiDireccion(double X, double Y) {
		Posicion pos = new Posicion(X, Y);
		this.MiDireccion = pos.normalizar();
		;
	};

	public void setVelocidad(int Veloci) {
		this.MiVelocidad = Veloci;
	};

	public void setMiPosicion(Posicion Pos) {
		this.MiPosicion = Pos;
	};

	/**
	 * Devuelve la referencia a la posicion que se mueve que es la posicion a la
	 * cual se mueve
	 */
	public Posicion meMuevoA() {
		this.setMiPosicionVieja(this.MiPosicion);
		this.setMiPosicion(this.getMiPosicion().sumarPosicion(
				(this.MiDireccion.multiplicarPosicion(this.MiVelocidad))));
		return this.getMiPosicion();
	}

	/**
	 * Aca en hago, el objeto bola se mueve, y luego se fija si intercepto a
	 * algun otro objeto, en ese caso reacciona cambiando la direccion
	 * 
	 * @return una posicion que es la nueva
	 */
	public Posicion hago() {
		boolean choque = false;
		this.meMuevoA(); // aqui debajo se fija si choco
		Iterator it = Controlador.controlador.ListaChocables.iterator();
		while ((it.hasNext()) && (!choque)) {
			Chocable elemChoc = (Chocable) it.next();
			if ((elemChoc.meToca(this)) && (this != elemChoc)
					&& (elemChoc.getClase() == "Ladrillo")) {
				this.setMiPosicion(elemChoc.dondeMeToca(this));
				this.MiDireccion = MiDireccion.reflejar((elemChoc
						.miNormal(this)));
				this.setMiPosicion(this.getMiPosicion().sumarPosicion(
						(this.MiDireccion.multiplicarPosicion(0.1))));
				// MiDireccion.torcer();
				elemChoc.meChocaron(this);
				choque = true;
			}
		}
		if (choque) {
			this.setVivo(false);
			this.setMiPosicion(null);
			this.deleteObservers();
		}
		setChanged();// estas dos lineas le avisan a board view que se cambio
						// y que dibuje todo de nuevo
		// notifyObservers();
		return getMiPosicion();
		// .sumarPosicion(this.getMiDireccion().invertir().multiplicarPosicion(this.getMiRadio()))
	}

	/**
	 * @param listChocables
	 *            the listChocables to set
	 */
	public void setListaChocables(ColChocables listChocables) {
		ListaChocables = listChocables;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see tp.Chocable#dondeMeToca(tp.Chocable) v 1.2 le puse invertir ver si
	 *      anda
	 */
	public Posicion dondeMeToca(Chocable elem) {
		while (this.getMiPosicion().distanciaA(elem.getMiPosicion()) < (this
				.getMiRadio() * 2)) {
			Posicion diferencia = elem.getMiPosicion().invertir();
			diferencia = diferencia.sumarPosicion(this.getMiPosicion());
			diferencia = diferencia.normalizar();
			diferencia = diferencia.multiplicarPosicion(0.01);
			this.setMiPosicion(this.getMiPosicion().sumarPosicion(diferencia));
		}
		Posicion posi = this.getMiPosicion().invertir();
		posi = posi.sumarPosicion(elem.getMiPosicion());
		posi = posi.normalizar();
		posi = posi.multiplicarPosicion(this.getMiRadio());
		posi = posi.sumarPosicion(this.getMiPosicion());
		return posi;
	}

	/**
	 * En este caso la bola cambia de direccion deacuerdo a donde la chocaron
	 * 
	 * @param recibe
	 *            el obj que lo choco
	 */
	public void meChocaron(Chocable elem) {
		this.setVivo(false);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see tp.Chocable#meToca(tp.Chocable)
	 */
	public boolean meToca(Chocable elem) {
		if (elem.getClase() == "Ladrillo") {
			double dist = this.getMiPosicion().distanciaA(elem.getMiPosicion());
			if (dist <= (this.getMiRadio() * 2)) {
				return true;
			}
		}
		return false;
	}

	public boolean meToca(Posicion pos) {
		if ((pos.getX() > (this.MiPosicion.getX() - this.MiRadio / 2) && (pos
				.getX() < (this.MiPosicion.getX()) + this.MiRadio / 2))) {
			if ((pos.getY() > (this.MiPosicion.getY() - this.MiRadio / 2) && (pos
					.getY() < (this.MiPosicion.getY()) + this.MiRadio / 2))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @return the miPosicion
	 */
	public Posicion getMiPosicion() {
		return MiPosicion;
	}

	/**
	 * @return the miPosicionVieja
	 */
	public Posicion getMiPosicionVieja() {
		return MiPosicionVieja;
	}

	/**
	 * @param miPosicionVieja
	 *            the miPosicionVieja to set
	 */
	public void setMiPosicionVieja(Posicion miPosicionVieja) {
		this.MiPosicionVieja = miPosicionVieja;
	};

	/**
	 * devuelve la normale que pueden interesar
	 * 
	 * @param recibe
	 *            de donde se le produce el choque (posicion y direccion)
	 * @return devuelve la normal que puede interesar
	 */
	public Posicion miNormal(Chocable elem) {
		Posicion Normal = (elem.getMiPosicion().invertir().sumarPosicion(this
				.dondeMeToca(elem)));
		if (this.getMiPosicion().sumarPosicion(Normal).equals(
				this.dondeMeToca(elem))) {
			return Normal;
		}
		return Normal.invertir();
	}

	/**
	 * devuelve la direccion de la bola
	 * 
	 * @param devuelve
	 *            la direccion
	 */
	public Posicion getMiDireccion() {
		return this.MiDireccion;
	}

	/**
	 * @return the miRadio
	 */
	public double getMiRadio() {
		return MiRadio;
	}

	/**
	 * @param miRadio
	 *            the miRadio to set
	 */
	public void setMiRadio(double miRadio) {
		MiRadio = miRadio;
	}

	/**
	 * @return El nombre del tipo de instancia
	 */
	public String getClase() {
		return Clase;
	}

	public boolean isVivo() {
		return vivo;
	}

	public void setVivo(boolean vivo) {
		this.vivo = vivo;
	}

	public Component getMiVista() {
		return miVista;
	}
}
